package cn.com.rexen.rplus.sa.controller;

import cn.com.rexen.rplus.controller.CURDControllerSupport;
import cn.com.rexen.rplus.core.criteria.Criteria;
import cn.com.rexen.rplus.core.criteria.Page;
import cn.com.rexen.rplus.core.criteria.PageRequest;
import cn.com.rexen.rplus.core.criteria.Pageable;
import cn.com.rexen.rplus.core.service.IService;
import cn.com.rexen.rplus.core.utils.IDGeneratorUUID;
import cn.com.rexen.rplus.core.utils.StringUtils;
import cn.com.rexen.rplus.sa.entity.*;
import cn.com.rexen.rplus.sa.model.*;
import cn.com.rexen.rplus.sa.service.OperateService;
import cn.com.rexen.rplus.sa.service.PermissionService;
import cn.com.rexen.rplus.sa.service.ResourceService;
import cn.com.rexen.rplus.sa.service.RoleService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 角色Controller.
 * 
 * @author zhanghai
 */
@Controller
@RequestMapping(value = RoleController.REQUEST_PATH)
public class RoleController extends CURDControllerSupport<Role,RoleVO> {

    /**
     * role模块路径.
     */
    public static final String REQUEST_PATH = "role";
    /**
     * 角色Service.
     */
    @Autowired
    private RoleService roleService;

    /**
     * 权限service.
     */
    @Autowired
    private PermissionService permissionService;

    /**
     * 操作service.
     */
    @Autowired
    private OperateService operateService;

    /**
     * 资源service.
     */
    @Autowired
    private ResourceService resourceService;

    /**
     * 角色对象.
     */
    private Role role;

    /**
     * 模块初始化.
     * 
     * @return ModelAndView.
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public ModelAndView index() {
        ModelAndView mav = new ModelAndView("/sa/role");
        return mav;
    }

    /*
     * (non-Javadoc)
     *
     * @see cn.com.rexen.rplus.controller.CURDControllerSupport#getEntity()
     */
    @Override
    public Role getEntity() {
        if (role == null) {
            role = new Role();
        }
        return role;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#getEntityService()
     */
    @Override
    protected IService getEntityService() {
        return roleService;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#doList(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    public Page<Role> doList(HttpServletRequest request, HttpServletResponse response) {
        Criteria criteria = roleService.getCriteria(Role.class);

        String pageSize = request.getParameter("pageSize");
        String page = request.getParameter("page");
        Pageable pageable = new PageRequest(page == null ? 0 : Integer.parseInt(page), pageSize == null ? DEFAULT_PAGESIZE
                : Integer.parseInt(pageSize));
        criteria.setPageable(pageable);
        Page<Role> findWithPage = roleService.findWithPage(criteria);

        return findWithPage;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#afterList(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
     * org.springframework.ui.ModelMap, java.util.List)
     */
    @Override
    protected void afterList(HttpServletRequest request, HttpServletResponse response, ModelMap mm, Page page) {
        List<RoleVO> roleVOList = new ArrayList<RoleVO>();
        for (Object object : page.getContent()) {
            Role role = (Role) object;
            String parentid = role.getParentid();
            String parentName = null;
            if (StringUtils.isNotEmpty(parentid)) {
                Role roleParent = roleService.get(Role.class, role.getParentid());
                parentName = roleParent != null ? roleParent.getName() : "";
            } else {
                parentName = "";
            }
            List<Resource> resourceList = resourceService.getResourceListByRoleId(role.getId());
            List<PermissionVO> pvoList = new ArrayList<PermissionVO>();
            for (Resource resource : resourceList) {
                PermissionVO permissionVO = new PermissionVO();
                ResourceVO resourceVO = new ResourceVO(resource.getId(), resource.getName(), resource.getParentgroup(),
                        resource.getParentgroup(), null, null);
                permissionVO.setSource(resourceVO);
                pvoList.add(permissionVO);
            }
            roleVOList.add(new RoleVO(role.getId(), role.getName(), parentName, parentid, pvoList));

        }
        mm.addAttribute("data", roleVOList);
        PageVO pageVO = new PageVO(page.getTotalPages(), page.getNumber(), page.getTotalElements());
        mm.addAttribute("page", pageVO);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#onShow(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
     * java.lang.Object, org.springframework.ui.ModelMap)
     */
//    @Override
    protected RoleVO onShow(HttpServletRequest request, HttpServletResponse response, Role o, ModelMap mm) {
        if (o == null) {
            return new RoleVO();
        }
        Role role = (Role) o;
        List<Permission> permissionList = permissionService.getPermissionByRoleId(role.getId());
       
        Role roleParent = roleService.get(Role.class, role.getParentid());
        String parentName  = roleParent != null ? roleParent.getName() : "";

        RoleVO roleVO = new RoleVO(role.getId(), role.getName(), parentName, role.getParentid());

        List<Resource> resourceIdList = new ArrayList<Resource>();

        for (Permission permission : permissionList) {
            Resource resource = permission.getResource();
            List<Operate> operateL = getOperateListByResourceId(resource.getId(), permission, role.getId());

            if (resourceIdList.contains(resource)) {
                continue;
            }
            resourceIdList.add(permission.getResource());
            ResourceVO rv = new ResourceVO(resource.getId(), resource.getName(), resource.getParentgroup(),
                    resource.getParentgroup());

            PermissionVO pv = new PermissionVO();
            pv.setOp(convertEntityToVO(operateL));
            pv.setId(permission.getId());
            pv.setSource(rv);

            List<PermissionVO> premissions = roleVO.getPremission();
            premissions.add(pv);
        }
        return roleVO;
    }

    private List<OperateVO> convertEntityToVO(List<Operate> operates) {
        List<OperateVO> list = new ArrayList<OperateVO>();
        for (Operate operate : operates) {
            OperateVO ov = new OperateVO(operate.getId(), operate.getName());
            ov.setEnabled(operate.isEnabled());
            list.add(ov);
        }
        return list;
    }

    private List<Operate> getOperateListByResourceId(String resourceId, Permission permission, String roleId) {
        List<Operate> operateList = new ArrayList<Operate>();
        List<Permission> permissionByResourceId = permissionService.getPermissionByResourceId(resourceId);

        for (Permission permission2 : permissionByResourceId) {
            Operate operate = permission2.getOperate();
            Role role2 = roleService.getRoleIdAndPermissionId(roleId, permission2.getId());
            if (role2 == null) {
                operate.setEnabled(false);
            } else {
                operate.setEnabled(true);
            }
            operateList.add(operate);
        }
        return operateList;
    }

    // List<OperateVO> ovList = new ArrayList<OperateVO>();
    //
    // Resource resource = permission.getResource();
    // ResourceVO rv = new ResourceVO(resource.getId(),resource.getName(),
    // resource.getParentgroup(),resource.getParentgroup());
    //
    // List<Operate> operateL = new ArrayList<Operate>();
    // List<Permission> permissionByResourceId =
    // permissionService.getPermissionByResourceId(resource.getId());
    //
    // for (Permission permission2 : permissionByResourceId) {
    // operateL.add(permission2.getOperate());
    // }
    //
    // Operate operate2 = permission.getOperate();
    //
    // for (Operate operate : operateL) {
    // OperateVO ov = new OperateVO(operate.getId(), operate.getName());
    // if (operate.getId().equals(operate2.getId())) {
    // ov.setEnabled(true);
    // } else {
    // ov.setEnabled(false);
    // }
    // ovList.add(ov);
    // }
    //
    // PermissionVO pv = new PermissionVO();
    // pv.setId(permission.getId());
    // pv.setSource(rv);
    // pv.setOp(ovList);
    // List<PermissionVO> premissions = roleVO.getPremission();
    // premissions.add(pv);
    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#beforeSave(javax.
     * servlet .http.HttpServletRequest, java.lang.Object,
     * org.springframework.validation.BindException,
     * org.springframework.ui.ModelMap)
     */
    @Override
    protected void beforeSave(HttpServletRequest request, HttpServletResponse response, RoleVO entity,
            BindException errors, ModelMap mm) {
        role = new Role();
        role.setId(roleService.generateId());
        role.setApp(getApps());
        String parentId = entity.getParentid();
        if (StringUtils.isEmpty(parentId)) {
            parentId = ROOT;
        }
        role.setParentid(parentId);
        role.setName(entity.getName());
        List<PermissionVO> premissionVOList = entity.getPremission();
        Set<RolePermission> rolePermissions = new HashSet<RolePermission>();
        for (PermissionVO permissionVO : premissionVOList) {
            // String permissionVOId = permissionVO.getId();
            // Permission permission = permissionService.get(Permission.class,
            // permissionVOId);
            List<OperateVO> op = permissionVO.getOp();
            ResourceVO source = permissionVO.getSource();
            for (OperateVO operateVO : op) {
                if (operateVO.isEnabled()) {
                    Permission permission = permissionService.getPermissionByResourceIdAndOperateId(source.getId(),
                            operateVO.getId());
                    RolePermission rp = new RolePermission(IDGeneratorUUID.generatorId(), role, permission);
                    rolePermissions.add(rp);
                    //                    role.addRolePermissions(rp);
                }
            }
        }
        role.setRolePermissions(rolePermissions);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#beforeUpdate(javax
     * .servlet.http.HttpServletRequest, java.lang.Object,
     * org.springframework.validation.BindException,
     * org.springframework.ui.ModelMap, java.lang.String)
     */
    @Override
    protected void beforeUpdate(HttpServletRequest request, HttpServletResponse response, RoleVO entity,
            BindException errors, ModelMap mm, String id) {
        role = roleService.get(Role.class, id);
        if(id.equals(entity.getParentid())){
            throw new RuntimeException("父节点与本节点重复.");
        }
        role.setId(id);
        role.setName(entity.getName());
        role.setParentid(StringUtils.isEmpty(entity.getParentid())?ROOT:entity.getParentid());
        List<PermissionVO> premissionVOList = entity.getPremission();
        Set<RolePermission> rolePermissions = new HashSet<RolePermission>();
        for (PermissionVO permissionVO : premissionVOList) {
            List<OperateVO> op = permissionVO.getOp();
            ResourceVO source = permissionVO.getSource();
            for (OperateVO operateVO : op) {
                if (operateVO.isEnabled()) {
                    Permission permission = permissionService.getPermissionByResourceIdAndOperateId(source.getId(),
                            operateVO.getId());
                    RolePermission rp = new RolePermission(IDGeneratorUUID.generatorId(), role, permission);
                    rolePermissions.add(rp);

                }
            }
        }
        role.setRolePermissions(rolePermissions);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#doUpdate(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    public void doUpdate(HttpServletRequest request, HttpServletResponse response) {
        roleService.updateRolePermission(role);
    }

    /**
     * 通过角色父id获取资源列表.
     * 
     * @param parentId
     *            角色父id
     * @return 返回资源列表的json数据.
     */
    @RequestMapping(value = "/{parentId}/children", method = RequestMethod.GET)
    @ResponseBody
    public ModelMap children(@PathVariable String parentId) {
        ModelMap mm = new ModelMap();
        if (StringUtils.isNotEmpty(parentId)) {
            List<Role> list = roleService.getRoleByParentId(parentId);
            List<RoleVO> roleVOList = new ArrayList<RoleVO>();
            for (Role role : list) {
                Role roleParent = roleService.get(Role.class, role.getParentid());
                String parentName = roleParent != null ? roleParent.getName() : "";
                String type = "item";
                List<Role> clientRoleList = roleService.getRoleByParentId(role.getId());
                if (clientRoleList != null && clientRoleList.size() > 0) {
                    type = "folder";
                }
                roleVOList.add(new RoleVO(role.getId(), role.getName(), parentName, role.getParentid(), type));
            }
            mm.addAttribute("data", roleVOList);
        }
        return mm;
    }
    
    @Override
    public void doDelete(Object object) throws Exception {
        Role role = (Role) object;
        List<Role> isItemList = roleService.getRoleByParentId(role.getId());
        if(isItemList!=null&&isItemList.size()>0){
            throw new RuntimeException("有子结点不允许删除.");
        }
        roleService.delete(role);
    }
}
